using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Media.Imaging;
using System.Collections.Specialized;
using System.Windows.Controls;


// Thumb DB is service based.
// A XML export will define the DB
// User will use Path to retrice thumb photo path.
// Thumb DB will not validate photo unless requested.
// Photo vlidation based on the modified date. If thumb modified date != real photo mod date, recreate.
// Will report how many photo recreated.
// If requested photo is missing, recreate.


namespace PhotoDemo
{
    public class ImageFile
    {
        public ImageFile(string path)
        {
            _path = path;
            _uri = new Uri(_path);
            _image = BitmapFrame.Create(_uri);
        }

        public override string ToString()
        {
            return Path;
        }

        private String _path;
        public String Path { get { return _path; } }
        private Uri _uri;
        public Uri Uri { get { return _uri; } }
        private BitmapFrame _image;
        public BitmapFrame Image { get { return _image; } }
    }

    // Need An Output file to export and import.
    // When Import, the missing folders will be searched and included, but we don't care existing folders.
    // If refreshing all desired, just delete the import file.
    public class MediaFolder : ObservableCollection<MediaFolder>
    {
        public MediaFolder() {}
        public MediaFolder(String path) : this(new DirectoryInfo(path)) { }
        public MediaFolder(DirectoryInfo dir) { Directory = dir; }

        public void Update()
        {
            String[] imageSupportList = _imageSupport.Split(new String[] { "<>" }, StringSplitOptions.RemoveEmptyEntries);
            String[] videoSupportList = _videoSupport.Split(new String[] { "<>" }, StringSplitOptions.RemoveEmptyEntries);
            _imagePaths = new ObservableCollection<string>();
            _videoPaths = new ObservableCollection<string>();
            _subFolders = new ObservableCollection<MediaFolder>();
            if (!_directory.Exists) return; 
 
            foreach (FileInfo file in _directory.GetFiles())
            {
                String tempExt = file.Extension.ToLower();
                foreach (String imageSupport in imageSupportList)
                    if (tempExt == imageSupport)
                        _imagePaths.Add(file.FullName);
                foreach (String videoSupport in videoSupportList)
                    if (tempExt == videoSupport)
                        _imagePaths.Add(file.FullName);
            }

            foreach (DirectoryInfo subDir in _directory.GetDirectories())
                _subFolders.Add(new MediaFolder(subDir));
        }

        // This only creates new folders and remove missing folders; it does not care existing images and videos.
        // Use Update() to re-create everything instead.
        public void Reconcile()
        {   
            // Remove Missing SubFolders
            ObservableCollection<MediaFolder> _missingSubFolders = new ObservableCollection<MediaFolder>();
            foreach (MediaFolder subFolder in _subFolders)
                if (! new DirectoryInfo(subFolder.Path).Exists)
                    _missingSubFolders.Add(subFolder);
            foreach (MediaFolder missingSubFolder in _missingSubFolders)
                _subFolders.Remove(missingSubFolder);

            // Add New SubFolders
            foreach (DirectoryInfo subDir in _directory.GetDirectories())
            {
                String subDirFullName = subDir.FullName.ToUpper();
                bool needToAdd = true;
                foreach (MediaFolder subFolder in _subFolders)
                {
                    if (subFolder.Path.ToUpper() == subDirFullName)
                    {
                        needToAdd = false;
                        break;
                    }
                }
                if (needToAdd) _subFolders.Add(new MediaFolder(subDir));           
            }
        }

        // In XML format for exporting.
        public override String ToString()
        {
            String result = "<MediaFolder>\r\n";
            result += "<_path>" + _path + "</_path>\r\n";
            
            result += "<_imagePaths>\r\n";
            foreach (String imagePath in _imagePaths)
                result += "<_path>" + imagePath + "</_path>\r\n";
            result += "</_imagePaths>\r\n";
            
            result += "<_videoPaths>\r\n";
            foreach (String videoPath in _videoPaths)
                result += "<_path>" + videoPath + "</_path>\r\n";
            result += "</_videoPaths>\r\n";

            foreach (MediaFolder subFolder in _subFolders)
                result += subFolder.ToString();

            result += "</MediaFolder>\r\n";
            return result;
        }

        // Parse ToString format. Does not validate directories and files.
        public void Parse(System.Xml.XmlTextReader reader)
        {
            reader.ReadStartElement("MediaFolder");

            reader.ReadStartElement("_path");
            _path = reader.ReadString();
            _directory = new DirectoryInfo(_path);
            _name = _directory.Name;
            _uri = new Uri(_path);
            reader.ReadEndElement();

            reader.ReadStartElement("_imagePaths");
            try
            {
                while (!reader.EOF)
                {
                    reader.ReadStartElement("_path");
                    _imagePaths.Add(reader.ReadString());
                    reader.ReadEndElement();
                }
            }
            catch (Exception e)
            {
                reader.ReadEndElement();
            }

            reader.ReadStartElement("_videoPaths");
            try
            {
                while (!reader.EOF)
                {
                    reader.ReadStartElement("_path");
                    _videoPaths.Add(reader.ReadString());
                    reader.ReadEndElement();
                }
            }
            catch (Exception e)
            {
                reader.ReadEndElement();
            }

            while (reader.IsEmptyElement) reader.Read();
            while (reader.IsStartElement("MediaFolder"))
            {
                MediaFolder newSubFolder = new MediaFolder();
                newSubFolder.Parse(reader);
                _subFolders.Add(newSubFolder);
                while (reader.IsEmptyElement) reader.Read();
            }
            reader.ReadEndElement();
        }

        #region member fields
        private String _name = "";
        public String Name { get { return _name; } }
        private String _path = "";
        public String Path { set { Directory = new DirectoryInfo(value); } get { return _path; } }
        private Uri _uri;
        public Uri Uri { get { return _uri; } }
        private DirectoryInfo _directory;
        public DirectoryInfo Directory 
        {
            set
            {
                _directory = value;
                _name = _directory.Name;
                _path = _directory.FullName;
                _uri = new Uri(_path);
                Update();

                if (!_directory.Exists) _name += " IS MISSING"; 
            }
            get
            {
                return _directory;
            }
        }

        public static String _imageSupport = "";
        public static String _videoSupport = "";
        public ObservableCollection<String> _imagePaths = new ObservableCollection<string>();
        public ObservableCollection<String> _videoPaths = new ObservableCollection<string>();
        public ObservableCollection<MediaFolder> _subFolders = new ObservableCollection<MediaFolder>();
        #endregion
    }

    // Store Self Photo List, Child Photo List, Level 2 Photo Thumb (5 Per Child or x), Level 3 Photo Thumb (1 Per Child).
    public class MediaView
    {

    }

    public


    public class PhotoList : ObservableCollection<ImageFile>
    {
        public PhotoList() { }

        public PhotoList(string path) : this(new DirectoryInfo(path)) { }

        public PhotoList(DirectoryInfo directory)
        {
            _directory = directory;
            Update();
        }

        public string Path
        {
            set
            {
                _directory = new DirectoryInfo(value);
                Update();
            }
            get { return _directory.FullName; }
        }

        public DirectoryInfo Directory
        {
            set
            {
                _directory = value;
                Update();
            }
            get { return _directory; }
        }
        private void Update()
        {
            MediaFolder._imageSupport = ".jpg";
            MediaFolder._videoSupport = ".wmv";
            MediaFolder tempMF = new MediaFolder("..\\..\\Photos");
            Console.WriteLine(tempMF);

            foreach (String f in tempMF._imagePaths)
            {
                Add(new ImageFile(f));
            }
            foreach (MediaFolder mf in tempMF._subFolders)
                foreach (String f in mf._imagePaths)
                    Add(new ImageFile(f));
        
            //System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader("..\\..\\Photos\\export.xml");
            //tempMF = new MediaFolder();
            //tempMF.Parse(reader);
            //Console.WriteLine(tempMF);
            //tempMF.Reconcile();
            //Console.WriteLine(tempMF);
            
            Console.WriteLine("");

        }

        DirectoryInfo _directory;
    }

    public class PrintType
    {
        public PrintType(string description, double cost)
        {
            _description = description;
            _cost = cost;
        }

        public override string ToString()
        {
            return _description;
        }

        private string _description;
        public String Description {get {return _description; }}

        private double _cost;
        public double Cost { get { return _cost; } }
    }

    public class PrintTypeList : ObservableCollection<PrintType>
    {
        public PrintTypeList()
        {
            Add(new PrintType("4x6 Print", 0.15));
            Add(new PrintType("Greeting Card", 1.49));
            Add(new PrintType("T-Shirt", 14.99));
        }
    }

    public class PrintBase : INotifyPropertyChanged
    {
        public PrintBase(BitmapSource photo, PrintType printtype, int quantity)
        {
            Photo = photo;
            PrintType = printtype;
            Quantity = quantity;
        }

        public PrintBase(BitmapSource photo, string description, double cost)
        {
            Photo = photo;
            PrintType = new PrintType(description, cost);
            Quantity = 0;
        }

        private BitmapSource _photo;
        public BitmapSource Photo
        {
            set { _photo = value; OnPropertyChanged("Photo"); }
            get { return _photo; }
        }

        private PrintType _PrintType;
        public PrintType PrintType
        {
            set { _PrintType = value; OnPropertyChanged("PrintType"); }
            get { return _PrintType; }
        }

        private int _quantity;
        public int Quantity
        {
            set { _quantity = value; OnPropertyChanged("Quantity"); }
            get { return _quantity; }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(String info)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(info));
        }

        public override string ToString()
        {
            return PrintType.ToString();
        }
    }

    public class Print : PrintBase 
    {
        public Print(BitmapSource photo) : base(photo, "4x6 Print", 0.15) { }
    }

    public class GreetingCard : PrintBase
    {
        public GreetingCard(BitmapSource photo) : base(photo, "Greeting Card", 1.49) { }
    }

    public class TShirt : PrintBase
    {
        public TShirt(BitmapSource photo) : base(photo, "T-Shirt", 14.99) { }
    }

    public class PrintList : ObservableCollection<PrintBase> { }


}
